#include <stdio.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

#include "pal/lane_cmd_parse.h"
#include "userLog.h"
#include "CxlUtil.h"
#include "common/configParser.h"

#include "vzLibuv.h"
#include "pal/vz_app.h"
#include "pal/vz_protocol.h"
#include "hal/imx6/src/hal_gps_uv.h"

static void PAL_VZ_Connect(uv_timer_t *timer);
static void vz_recv_response(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf);
static void _VZ_RecvHandle(const uv_buf_t *buf, int nLen, VzAppStruct *vzAppStruct);
static void _VZ_HeardBeatTask(uv_timer_t *handle);
static void write_cb(uv_write_t *req, int status);
static void vz_task(uv_connect_t *client, int status);
static void alloc_buffer_for_vz_app(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);

static uint8_t hb_log_num = 0;
static bool isStartCalibrationV2 = false;

static void uv_write_with_test_connecting(VzAppStruct *vzAppStruct, uint8_t *buf, uint32_t len)
{
	if (vzAppStruct->recvResponseCount <= 3)
	{
		write_req_t *wr_rq = (write_req_t *)malloc(sizeof(write_req_t));
		wr_rq->buf = uv_buf_init(buf, len);

		wr_rq->req.data = vzAppStruct;
		uv_write((uv_write_t *)wr_rq, vzAppStruct->uv.client.handle, &wr_rq->buf, 1, write_cb);
		vzAppStruct->recvResponseCount++;
	}
	else
	{
		LOG_ERROR("相机[id:%d（%s）] socket写失败， 原因：超过%d次写都没收到服务器的响应", vzAppStruct->vzCamId, vzAppStruct->remark, vzAppStruct->recvResponseCount);
		if (uv_is_closing((uv_handle_t *)(vzAppStruct->uv.client.handle)) == 0)
		{
			uv_close((uv_handle_t *)(vzAppStruct->uv.client.handle), NULL);
		}

		setPrivateVzlibuvStruct(&(vzAppStruct->uv));
		vzClearInterval();
		vzSetTimeout(PAL_VZ_Connect, VZ_RECONNECT_TIME_OUT);
		vzAppStruct->isConnected = false;
		vzAppStruct->recvResponseCount = 0;
		free(buf);
	}
}

// 相机写socket回调
static void write_cb(uv_write_t *req, int status)
{
	VzAppStruct *vzAppStruct = (VzAppStruct *)req->data;
	if (status)
	{
		const uint8_t *err_str = uv_err_name(status);
		write_req_t *wr = (write_req_t *)req;
		LOG_ERROR("相机[id:%d（%s）] socket写失败， 原因：%s；失败内容：", vzAppStruct->vzCamId, vzAppStruct->remark, err_str);
		hzlog_error(userLog, wr->buf.base, wr->buf.len);
		if (status == 0)
		{
			// Unknown system error 0 会内存泄露
			free((void *)err_str);
		}
		if (uv_is_closing((uv_handle_t *)(vzAppStruct->uv.client.handle)) == 0)
		{
			uv_close((uv_handle_t *)(vzAppStruct->uv.client.handle), NULL);
		}

		setPrivateVzlibuvStruct(&(vzAppStruct->uv));
		vzClearInterval();
		vzSetTimeout(PAL_VZ_Connect, VZ_RECONNECT_TIME_OUT);
		vzAppStruct->isConnected = false;
		vzAppStruct->recvResponseCount = 0;
	}
	free_write_req(req);
}

// 定时心跳任务回调
static void _VZ_HeardBeatTask(uv_timer_t *handle)
{
	VzAppStruct *vzAppStruct = getVzAppPtrFromUvTimmerInterval(handle);

	if (vzAppStruct->isConnected == true)
	{
		uint8_t *aHeartBeatCmd = malloc(128);

		memset(aHeartBeatCmd, 0, 128);
		int32_t ret = VZ_GenCmdHeartBeat(aHeartBeatCmd, 128);
		uv_write_with_test_connecting(vzAppStruct, aHeartBeatCmd, ret);
	}
	else
	{
		LOG_ERROR("相机[id:%d（%s）] 服务器已断开，重新连接后发送心跳", vzAppStruct->vzCamId, vzAppStruct->remark);
	}
}

// 相机各种事件注册
static void vz_task(uv_connect_t *client, int status)
{
	VzAppStruct *vzAppStruct = getVzAppPtrFromUvConnect(client);
	if (status < 0)
	{
		vzAppStruct->isConnected = false;
		LOG_ERROR("相机[id:%d（%s）] 服务器 %s:%d 链接失败， 原因：%s", vzAppStruct->vzCamId, vzAppStruct->remark, vzAppStruct->vzCamIp, vzAppStruct->vzCamPort, uv_strerror(status));
		setPrivateVzlibuvStruct(&(vzAppStruct->uv));
		vzSetTimeout(PAL_VZ_Connect, VZ_RECONNECT_TIME_OUT);
		return;
	}

	vzAppStruct->isConnected = true;
	LOG_INFO("连接成功，注册相机[id:%d（%s）] 心跳定时任务", vzAppStruct->vzCamId, vzAppStruct->remark);

	// 接收事件注册
	client->handle->data = vzAppStruct;
	uv_read_start(client->handle, alloc_buffer_for_vz_app, vz_recv_response);

	// 注册相机
	uint8_t *buf = (uint8_t *)malloc(128 * sizeof(uint8_t));
	int32_t ret = VZ_GenCmd_set_ivsresult(buf, 128, true);
	uv_write_with_test_connecting(vzAppStruct, buf, ret);

	// 发送心跳定时任务
	setPrivateVzlibuvStruct(&(vzAppStruct->uv));
	vzInterval(_VZ_HeardBeatTask, VZ_HEART_BEAT_TIME);
}

static void vz_recv_response(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf)
{
	VzAppStruct *vzAppStruct = (VzAppStruct *)client->data;
	if (nread > 0)
	{
		_VZ_RecvHandle(buf, nread, vzAppStruct);
	}
	else if (nread < 0)
	{
		if (nread != UV_EOF)
		{
			LOG_ERROR("读相机[id:%d（%s）] socket错误 %s", vzAppStruct->vzCamId, vzAppStruct->remark, uv_err_name(nread));
			if (uv_is_closing((uv_handle_t *)(vzAppStruct->uv.client.handle)) == 0)
			{
				uv_close((uv_handle_t *)(vzAppStruct->uv.client.handle), NULL);
			}
			setPrivateVzlibuvStruct(&(vzAppStruct->uv));
			vzClearInterval();
			vzSetTimeout(PAL_VZ_Connect, VZ_RECONNECT_TIME_OUT);
		}
	}

	free(buf->base);
}

static void PAL_VZ_Connect(uv_timer_t *timer)
{
	VzAppStruct *vzAppStruct = getVzAppPtrFromUvTimmerSetTimeOut(timer);

	setPrivateVzlibuvStruct(&(vzAppStruct->uv));
	vzConnect(vz_task);
}

VzAppStruct *vzAppStructArr = NULL;
int PAL_VZ_AppInit()
{
	uint8_t camNum = getCameraNum();
	VzCamInfoStruct *camInfo = getCameraInfo();
	uv_loop_t *loop = getLoop();

	vzAppStructArr = (VzAppStruct *)malloc(camNum * sizeof(VzAppStruct));
	memset(vzAppStructArr, 0, camNum * sizeof(VzAppStruct));
	uint8_t i = 0;
	for (i = 0; i < camNum; i++)
	{
		vzAppStructArr[i].vzCamId = camInfo[i].VZ_ID;
		vzAppStructArr[i].vzCamPort = camInfo[i].VZ_CAM_PORT;
		memcpy(vzAppStructArr[i].vzCamIp, camInfo[i].VZ_CAM_IP, MEM_SIZE(VzAppStruct, vzCamIp));
		memcpy(vzAppStructArr[i].remark, camInfo[i].remark, MEM_SIZE(VzAppStruct, remark));
		vzAppStructArr[i].accumulate_recvLen = 0;
		vzAppStructArr[i].reverse_pack_len = 0;
		vzAppStructArr[i].hold_pack_len = 0;
		vzAppStructArr[i].nextBufSize = sizeof(VZ_PACKET_T);
		vzAppStructArr[i].isHandleIvsPackSize = false;
		vzAppStructArr[i].isCalibration = camInfo[i].CALIBRATION == 1 ? true : false;
		// LOG_INFO("vzAppStructArr id:%d（%s） isCalibration:%d",
		// 		 vzAppStructArr[i].vzCamId, vzAppStruct->remark, vzAppStructArr[i].isCalibration);
		uv_timer_init(loop, &vzAppStructArr[i].uv.vzReq);
		uv_timer_init(loop, &vzAppStructArr[i].uv.mainWorkSetTimeOut);

		PAL_VZ_Connect(&(vzAppStructArr[i].uv.mainWorkSetTimeOut));
	}
}

static void _VZ_RecvHandle(const uv_buf_t *buf, int nLen, VzAppStruct *vzAppStruct)
{
	vzAppStruct->recvResponseCount = 0;
	//hzlog_info(userLog, buf->base, buf->len);
	// LOG_INFO("相机[id:%d（%s）] 收到%ld字节：", vzAppStruct->vzCamId,vzAppStruct->remark,  buf->len);
	uint8_t *vz_app_stream = vzAppStruct->vzAppStream;
	ssize_t *accumulate_recvLen = &(vzAppStruct->accumulate_recvLen);
	uint32_t *reverse_pack_len = &(vzAppStruct->reverse_pack_len);
	uint32_t *hold_pack_len = &(vzAppStruct->hold_pack_len);
	uint32_t *hold_pack_len_tmp = &(vzAppStruct->hold_pack_len_tmp);
	ssize_t *nextBufSize = &(vzAppStruct->nextBufSize);
	bool *isHandleIvsPackSize = &(vzAppStruct->isHandleIvsPackSize);

	uint8_t id = vzAppStruct->vzCamId;
	uint8_t *remark = vzAppStruct->remark;
	int32_t headLen = sizeof(VZ_HEAD_T);
	bool isRecvAPack = false;
	VZ_PACKET_T correctHead = {'V', 'Z'};
	VZ_PACKET_T ivsCorrectHead = {'I', 'R'};
	uint8_t jsonStartChar = '{';
	VZ_PACKET_T *pack = (VZ_PACKET_T *)buf->base;
	// if (buf->len < 500)
	// {
	// 	LOG_INFO("相机[id:%d（%s）] 收到的前8字节：", vzAppStruct->vzCamId,vzAppStruct->remark);
	// 	hzlog_info(userLog, buf->base, 8);
	// }
	if (memcmp(&correctHead, pack, 2) == 0 && *accumulate_recvLen == 0)
	{
		gps_t gps = getLastGps();
		memcpy(vzAppStruct->gga, gps.gps_gngga_data, MINMEA_MAX_LENGTH);
		memcpy(vzAppStruct->rmc, gps.gps_gnrmc_data, MINMEA_MAX_LENGTH);
		memset(vz_app_stream, 0, sizeof(vzAppStruct->vzAppStream));
		// 收到一个包，标定接下来需要收到的内容
		*reverse_pack_len = htonl(pack->stHead.unDataLen);
		*hold_pack_len = htonl(pack->stHead.unDataLen);
		// 剩余包长度为0是心跳
		// 如果一包收完，后续也不走else
		// LOG_DEBUG("相机[id:%d（%s）] 整包大小：%u", vzAppStruct->vzCamId,vzAppStruct->remark,  *hold_pack_len);
		if (*reverse_pack_len != 0 && *hold_pack_len != nLen)
		{
			*nextBufSize = *reverse_pack_len;
			memcpy(vz_app_stream, pack, sizeof(VZ_PACKET_T));
			// LOG_DEBUG("相机[id:%d（%s）] 下次要接收的大小：%lu", vzAppStruct->vzCamId,vzAppStruct->remark,  *nextBufSize);
			return;
		}
		*hold_pack_len_tmp = *hold_pack_len;
	}
	else if (*accumulate_recvLen < *hold_pack_len)
	{
		*reverse_pack_len -= nLen;
		*nextBufSize = *reverse_pack_len;

		// LOG_DEBUG("相机[id:%d（%s）] 此次收到大小：%d", vzAppStruct->vzCamId,vzAppStruct->remark,  nLen);
		// LOG_DEBUG("相机[id:%d（%s）] 下次要接收的大小：%ld", vzAppStruct->vzCamId,vzAppStruct->remark,  *nextBufSize);
		memcpy(vz_app_stream + sizeof(VZ_PACKET_T) + *accumulate_recvLen, buf->base, nLen);
		*accumulate_recvLen += nLen;
		// LOG_DEBUG("相机[id:%d（%s）] 累计收到的大小：%ld", vzAppStruct->vzCamId,vzAppStruct->remark,  *accumulate_recvLen);
		// LOG_DEBUG("相机[id:%d（%s）] 剩余需要收的大小：%d", vzAppStruct->vzCamId,vzAppStruct->remark,  *reverse_pack_len);
		if (0 != *reverse_pack_len)
		{
			return;
		}
		*hold_pack_len_tmp = *hold_pack_len;
		*accumulate_recvLen = 0;
		*reverse_pack_len = 0;
		*hold_pack_len = 0;
		*isHandleIvsPackSize = false;
		*nextBufSize = sizeof(VZ_PACKET_T);
		// LOG_DEBUG("相机[id:%d（%s）] 下次要接收的大小：%ld", vzAppStruct->vzCamId,vzAppStruct->remark,  *nextBufSize);
		pack = (VZ_PACKET_T *)vz_app_stream;
	}

	if (memcmp(&correctHead, pack, 2) == 0)
	{
		// if (*hold_pack_len_tmp > 0)
		// {
		// 	LOG_INFO("除了心跳的报文：");
		// 	hzlog_info(userLog, pack, *hold_pack_len_tmp > 100 ? 100 : *hold_pack_len_tmp + sizeof(VZ_HEAD_T));
		// }
		switch (pack->stHead.ucPacketType)
		{
		case VZ_DATA_TYPE_JSON: // 0
		{
			if (nLen < *reverse_pack_len)
			{
				memcpy(vz_app_stream, pack, nLen);
			}
			VZ_PACKET_T *mayBeIvsresult = (VZ_PACKET_T *)pack->acData;
			if (memcmp(&ivsCorrectHead, mayBeIvsresult, 2) == 0)
			{
				// FILE *p = fopen("camWithHoldPai", "wb");
				// int ret = fwrite(pack, 1, htonl(pack->stHead.unDataLen), p);
				// fflush(p);
				// LOG_INFO("写%d字节", ret);
				LOG_INFO("相机[id:%d（%s）] 照片识别数据", id, remark);
				TH_PlateResult *stDisc = malloc(sizeof(TH_PlateResult));
				memcpy(stDisc, (TH_PlateResult *)mayBeIvsresult->acData, sizeof(TH_PlateResult));

				// 业务逻辑
				VZ_PACKET_T *imgStarPtr = (VZ_PACKET_T *)((uint8_t *)mayBeIvsresult->acData + mayBeIvsresult->stHead.unDataLen);
				parseIvsResult(stDisc, imgStarPtr, vzAppStruct);
				free(stDisc);
			}
			else if (jsonStartChar == ((uint8_t *)mayBeIvsresult)[0])
			{

				bool parseResult = true;
				cJSON *responseJson;
				cJSON *statusCodeJson;
				cJSON *imgDataJson;
				cJSON *cmdKeyJson;
				//LOG_INFO("json data:%s", pack->acData);
				responseJson = cJSON_Parse(pack->acData);
				if (responseJson != NULL)
				{
					cmdKeyJson = cJSON_GetObjectItem(responseJson, "cmd");
					statusCodeJson = cJSON_GetObjectItem(responseJson, "state_code");
					imgDataJson = cJSON_GetObjectItem(responseJson, "imgdata");
					if (cmdKeyJson != NULL && statusCodeJson != NULL)
					{
						uint16_t code = statusCodeJson->valueint;
						if (code != 200)
						{
							LOG_ERROR("相机指令错误码：%d", code);
							goto JSON_PARSE_END;
						}
						if (memcmp(VZ_CMD_GET_SNAP_SHOT, cmdKeyJson->valuestring, strlen(VZ_CMD_GET_SNAP_SHOT)) == 0)
						{
							LOG_INFO("收到%s相机指令回复", VZ_CMD_GET_SNAP_SHOT);
							uint8_t *camDtatBase64 = imgDataJson->valuestring;
							parseSnapShotResult(camDtatBase64, vzAppStruct);
						}
					}
					else
					{
						parseResult = false;
						goto JSON_PARSE_END;
					}
				}
				else
				{
					parseResult = false;
					goto JSON_PARSE_END;
				}
			JSON_PARSE_END:
				cJSON_Delete(responseJson);
				if (parseResult == false)
				{
					LOG_ERROR("相机返回的json解析失败");
					return;
				}
			}
			break;
		}
		case VZ_DATA_TYPE_HB:
		{
			hb_log_num++;
			if (hb_log_num > HB_LOG_MAX_NUM)
			{
				hb_log_num = 0;
				LOG_INFO("收到相机[id:%d（%s）] 心跳", id, remark);
			}
			break;
		}
		case VZ_DATA_TYPE_BIN:
		{
			LOG_INFO("相机[id:%d（%s）] 二进制数据", id, remark);
			break;
		}
		default:
		{
			LOG_ERROR("返回了未知的相机[id:%d（%s）] 数据类型: %d", id, remark, pack->stHead.ucPacketType);
		}
		}
		memset(vz_app_stream, 0, MEM_SIZE(VzAppStruct, vzAppStream));
	}
}

static void alloc_buffer_for_vz_app(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)
{
	VzAppStruct *vzAppStruct = (VzAppStruct *)handle->data;
	ssize_t nextBufSize = vzAppStruct->nextBufSize;

	buf->base = (uint8_t *)malloc(nextBufSize);
	memset(buf->base, 0, nextBufSize);
	buf->len = nextBufSize;
}

static uv_async_t calibrationEventV2;
static void calibrationEventV2Cb(uv_async_t *handle)
{
	bool *tmp = (bool *)handle->data;
	uint8_t camNum = getCameraNum();
	isStartCalibrationV2 = *tmp;

	for (size_t i = 0; i < camNum; i++)
	{
		VzAppStruct *vzAppStruct = (VzAppStruct *)(&vzAppStructArr[i]);
		if (vzAppStruct->isConnected == true)
		{
			if (isStartCalibrationV2 == true)
			{
				// 停止相机主动推送
				LOG_INFO("停止相机[id:%d（%s）]主动推送", vzAppStruct->vzCamId, vzAppStruct->remark);
				uint8_t *buf = (uint8_t *)malloc(128 * sizeof(uint8_t));
				int32_t ret = VZ_GenCmd_set_ivsresult(buf, 128, false);
				uv_write_with_test_connecting(vzAppStruct, buf, ret);
			}
			else
			{
				// 相机主动推送
				LOG_INFO("开启相机[id:%d（%s）]主动推送", vzAppStruct->vzCamId, vzAppStruct->remark);
				uint8_t *buf = (uint8_t *)malloc(128 * sizeof(uint8_t));
				int32_t ret = VZ_GenCmd_set_ivsresult(buf, 128, true);
				uv_write_with_test_connecting(vzAppStruct, buf, ret);
			}
		}
		else
		{
			LOG_ERROR("相机[id:%d（%s）] 未连接，无法发送enable: false命令", vzAppStruct->vzCamId, vzAppStruct->remark);
		}
	}
}

static void initCalibrationEventV2Event()
{
	static bool isInit = false;
	if (isInit == false)
	{
		calibrationEventV2.data = (bool *)malloc(sizeof(bool));
		uv_async_init(getLoop(), &calibrationEventV2, calibrationEventV2Cb);
		isInit = true;
	}
}

void dispatchStartCalibrationV2()
{
	initCalibrationEventV2Event();
	bool *tmp = (bool *)calibrationEventV2.data;
	*tmp = true;
	uv_async_send(&calibrationEventV2);
}

void dispatchStopCalibrationV2()
{
	initCalibrationEventV2Event();
	bool *tmp = (bool *)calibrationEventV2.data;
	*tmp = false;
	uv_async_send(&calibrationEventV2);
}

void dispatchTriggerToCamera()
{
	uint8_t camNum = getCameraNum();
	for (size_t i = 0; i < camNum; i++)
	{
		VzAppStruct *vzAppStruct = &vzAppStructArr[i];
		LOG_INFO("camera Id :%d vzAppStruct->isCalibration %d", vzAppStruct->vzCamId, vzAppStruct->isCalibration);

		if (vzAppStruct->isCalibration == true)
		{
			if (vzAppStruct->isConnected == true)
			{
				uint8_t *buf = (uint8_t *)malloc(128 * sizeof(uint8_t));
				int32_t ret = VZ_GenCmdGetSnapShot(buf, 128);
				LOG_INFO("相机[id:%d（%s）]发送snapshot命令", vzAppStruct->vzCamId, vzAppStruct->remark);
				uv_write_with_test_connecting(vzAppStruct, buf, ret);
			}
			else
			{
				LOG_ERROR("相机[id:%d（%s）] 未连接，无法发送trigger命令", vzAppStruct->vzCamId, vzAppStruct->remark);
			}
		}
	}
}

bool getIsStartCalibrationV2()
{
	return isStartCalibrationV2;
}